/**
 * Copyright 厦门中软海晟信息技术有限公司 版权所有 违者必究 2019
 */
package com.opencvjava.practise;

import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import static com.opencvjava.support.util.CvUtils.imshow;
import static com.opencvjava.support.util.CvUtils.mat;
import static org.opencv.imgcodecs.Imgcodecs.IMREAD_GRAYSCALE;
import static org.opencv.imgproc.Imgproc.CV_SHAPE_RECT;
import static org.opencv.imgproc.Imgproc.MORPH_OPEN;
import static org.opencv.imgproc.Imgproc.MORPH_TOPHAT;
import static org.opencv.imgproc.Imgproc.THRESH_BINARY;
import static org.opencv.imgproc.Imgproc.getStructuringElement;
import static org.opencv.imgproc.Imgproc.morphologyEx;
import static org.opencv.imgproc.Imgproc.threshold;

/**
 * @author : sunzb
 * @date: 2019/8/16
 */
@Service
public class Txm2 {
    Random random = new Random();

    public void test() {
        Mat gray = mat("txm.png", IMREAD_GRAYSCALE);
        Mat binary = new Mat();
        threshold(gray, binary, 127, 255, THRESH_BINARY);
        int total = (int) binary.total();
        int rows = binary.rows();
        int cols = binary.cols();
        byte[] biData = new byte[total];
        binary.get(0, 0, biData);
        imshow("阈值二值化", binary);
        Mat mid = new Mat(binary.size(), binary.type());
        byte[] midData = new byte[total];
        for (int i = 0; i < total; i++) {
            midData[i] = -1;
        }
        List<Map<String, Byte>> layers = new ArrayList<>();
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                layers.add(dfs(row, col, rows, cols, biData));
            }
        }
        if (!CollectionUtils.isEmpty(layers)) {
            int curRow, curCol, index;
            for (Map<String, Byte> layer : layers) {
                Iterator<Map.Entry<String, Byte>> ite = layer.entrySet().iterator();
                while (ite.hasNext()) {
                    Map.Entry<String, Byte> next = ite.next();
                    String key = next.getKey();
                    String[] point = StringUtils.split(key, ",");
                    curRow = Integer.parseInt(point[0]);
                    curCol = Integer.parseInt(point[1]);
                    index = curRow * cols + curCol;
                    midData[index] = next.getValue();
                }
            }
        }
        mid.put(0, 0, midData);
        imshow("mid", mid);
    }

    private Map<String, Byte> dfs(int row, int col, int rows, int cols, byte[] biData) {
        Map<String, Byte> result = new HashMap<>();
        LinkedList<String> bfs = new LinkedList<>();
        int curRow = row, curCol = col;
        if (biData[curRow * cols + curCol] == 0)
            bfs.push(curRow + "," + curCol);
        int color = random.nextInt(256);
        while (!bfs.isEmpty()) {
            String[] point = StringUtils.split(bfs.pop(), ",");
            curRow = Integer.parseInt(point[0]);
            curCol = Integer.parseInt(point[1]);
            int index = curRow * cols + curCol;
            result.put(curRow + "," + curCol, (byte) (color & 0xff));
            biData[index] = -1;
            if (curRow - 1 >= 0 && curCol - 1 >= 0) {
                int tlIndex = (curRow - 1) * cols + curCol - 1;
                if (biData[tlIndex] == 0)
                    bfs.push((curRow - 1) + "," + (curCol - 1));
            }
            if (curRow - 1 >= 0) {
                int topIndex = (curRow - 1) * cols + curCol;
                if (biData[topIndex] == 0)
                    bfs.push((curRow - 1) + "," + curCol);
            }
            if (curRow - 1 >= 0 && curCol + 1 < cols) {
                int trIndex = (curRow - 1) * cols + curCol + 1;
                if (biData[trIndex] == 0)
                    bfs.push((curRow - 1) + "," + (curCol + 1));
            }
            if (curCol - 1 >= 0) {
                int leftIndex = curRow * cols + curCol - 1;
                if (biData[leftIndex] == 0)
                    bfs.push(curRow + "," + (curCol - 1));
            }
            if (curCol + 1 < cols) {
                int rightIndex = curRow * cols + curCol + 1;
                if (biData[rightIndex] == 0)
                    bfs.push(curRow + "," + (curCol + 1));
            }
            if (curRow + 1 < rows && curCol - 1 >= 0) {
                int blIndex = (curRow + 1) * cols + curCol - 1;
                if (biData[blIndex] == 0)
                    bfs.push((curRow + 1) + "," + (curCol - 1));
            }
            if (curRow + 1 < rows) {
                int bottomIndex = (curRow + 1) * cols + curCol;
                if (biData[bottomIndex] == 0)
                    bfs.push((curRow + 1) + "," + curCol);
            }
            if (curRow + 1 < rows && curCol + 1 < cols) {
                int brIndex = (curRow + 1) * cols + curCol + 1;
                if (biData[brIndex] == 0)
                    bfs.push((curRow + 1) + "," + (curCol + 1));
            }
        }
        return result;
    }
}
